package com.googlecode.kipler.satisfiability.completion.strategy;

import java.util.ArrayList;
import java.util.List;

import com.googlecode.kipler.container.dl.WorldConstraintSystem;
import com.googlecode.kipler.container.dl.operational.FilterType;
import com.googlecode.kipler.container.dl.operational.RelatedIndividualWithTypeFilter;
import com.googlecode.kipler.container.dl.operational.RelatedIndividualWithTypeFilterFactory;
import com.googlecode.kipler.satisfiability.blocking.abox.ABoxBlockingStrategy;
import com.googlecode.kipler.satisfiability.blocking.abox.SHOIQDoubleBlocking;
import com.googlecode.kipler.satisfiability.completion.rule.individual.ABoxRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.AllValuesRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.AtLeastRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.AtMostRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.ChooseRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.IntersectionRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.LazyUnfoldingRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.NominalGuessRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.PositiveConceptDefinitionRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.SHOIQMergeStrategy;
import com.googlecode.kipler.satisfiability.completion.rule.individual.SameNominalMergeRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.SomeValuesRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.TransitivityRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.UnionRule;
import com.googlecode.kipler.satisfiability.reasoner.Reasoner;
import com.googlecode.kipler.satisfiability.reasoner.ReasonerException;


/**
 * 
 * @author İnanç Seylan
 * 
 */
public class SHOIQBasicCompletionStrategy implements CompletionStrategy {

	private PriorityBasedStrategy strategy;

	public SHOIQBasicCompletionStrategy(Reasoner reasoner) {
		strategy = new PriorityBasedStrategy();
		setReasoner(reasoner);
		ABoxBlockingStrategy blocking = new SHOIQDoubleBlocking();
		RelatedIndividualWithTypeFilter filter = RelatedIndividualWithTypeFilterFactory
				.getFilter(FilterType.TYPED_SAFE_NEIGHBOR);
		// SameNominalMergeRule is applied with highest priority.
		List<ABoxRule> ruleList = new ArrayList<ABoxRule>();
		ruleList.add(new SameNominalMergeRule());
		strategy.addIndividualRules(ruleList, true, new NominalFeeder());
		// Next NominalGuessRule and AtMostRule are applied for nominals.
		ruleList = new ArrayList<ABoxRule>();
		ruleList.add(new NominalGuessRule(getReasoner()));
		ruleList.add(new AtMostRule(getReasoner(), blocking,
				new SHOIQMergeStrategy()));
		strategy.addIndividualRules(ruleList, true, new NominalFeeder());
		// All other rules are applied with a lower priority.
		ruleList = new ArrayList<ABoxRule>();
		ruleList.add(new LazyUnfoldingRule());
		ruleList.add(new PositiveConceptDefinitionRule(blocking));
		ruleList.add(new IntersectionRule(blocking));
		ruleList.add(new AllValuesRule(blocking));
		ruleList.add(new TransitivityRule(blocking));
		ruleList.add(new UnionRule(getReasoner(), blocking));
		ruleList.add(new ChooseRule(getReasoner(), blocking));
		ruleList.add(new AtMostRule(getReasoner(), blocking,
				new SHOIQMergeStrategy()));
		ruleList.add(new SomeValuesRule(blocking, filter, false));
		ruleList.add(new AtLeastRule(blocking, filter, false));
		strategy
				.addIndividualRules(ruleList, true, new BasicIndividualFeeder());
	}

	@Override
	public void apply(WorldConstraintSystem currentWcs)
			throws ReasonerException {
		strategy.apply(currentWcs);
	}

	@Override
	public Reasoner getReasoner() {
		return strategy.getReasoner();
	}

	@Override
	public void setReasoner(Reasoner reasoner) {
		strategy.setReasoner(reasoner);
	}
}
